﻿using System.Collections.Generic;
using System.Xml;
using System.Data;
using SdmxMl.Helper;
using SdmxMl.Common;

namespace SdmxMl.Structure
{
    /// <summary>
    /// Base class for (Meta)Data flow references
    /// </summary>
    public class FlowRef
    {
        #region Properties

        public string tag;
        protected string tagFlowid;

        protected string uri;
        public string URI
        {
            get { return uri; }
            set { uri = value; }
        }

        protected string agencyId;
        public string AgencyId
        {
            get { return agencyId; }
            set { agencyId = value; }
        }
        protected string flowId;
        public virtual string FlowId
        {
            get { return flowId; }
            set { flowId = value; }
        }
        protected string version;
        public string Version
        {
            get { return version; }
            set
            {
                version = value;
                if (string.IsNullOrEmpty(version))
                    version = "1.0";
            }
        }

        #endregion //Properties

        #region Construction

        private void Init()
        {
            // Assume dataFlow by default
            tag = "DataflowRefType";
            tagFlowid = "DataflowID";

        }
        public FlowRef()
        {
            Init();
        }

        public FlowRef(XmlNode nodeArtefact, XmlNamespaceManager nsmgr)
        {
            Init();
            agencyId = Xmlhelper.GetNodeText(nodeArtefact, "./structure:AgencyID", nsmgr);
            URI = Xmlhelper.GetNodeText(nodeArtefact, "./structure:URN", nsmgr);
            Version = Xmlhelper.GetNodeText(nodeArtefact, "./structure:Version", nsmgr);

            flowId = Xmlhelper.GetNodeText(nodeArtefact, "./structure:DataflowID", nsmgr);
        }
        #endregion //Construction

        #region XML serialize

        public void WriteXml(XmlTextWriter xw, string prefix, string tag)
        {
            xw.WriteStartElement(prefix, tag, null);

            Xmlhelper.WriteElementIfExist(xw, prefix, "URN", URI);
            Xmlhelper.WriteElementIfExist(xw, prefix, "AgencyID", agencyId);
            Xmlhelper.WriteElementIfExist(xw, prefix, tagFlowid, FlowId);
            if (Version != "1.0")
                Xmlhelper.WriteElementIfExist(xw, prefix, "Version", Version);


            xw.WriteEndElement();
        }

        protected virtual void WriteFlowRefId(XmlTextWriter xw, string prefix)
        {
            Xmlhelper.WriteElementIfExist(xw, prefix, tagFlowid, FlowId);
        }

        #endregion // XML serialize

        #region String Representation

        public override string ToString()
        {
            return FlowId;
        }
        #endregion

    }

    /// <summary>
    /// Data flow reference
    /// </summary>
    public class DataFlowRef : FlowRef
    {
        #region Construction

        public DataFlowRef()
            : base()
        {
        }

        public DataFlowRef(XmlNode nodeArtefact, XmlNamespaceManager nsmgr)
            : base(nodeArtefact, nsmgr)
        {
        }
        #endregion
    }

    /// <summary>
    /// Metadata flow reference
    /// </summary>
    public class MetaDataFlowRef : FlowRef
    {
        #region Construction

        private void Init()
        {
            tag = "MetadataflowRefType";
            tagFlowid = "MetadataflowID";
        }

        public MetaDataFlowRef()
        {
            Init();
        }

        public MetaDataFlowRef(XmlNode nodeArtefact, XmlNamespaceManager nsmgr)
            : base(nodeArtefact, nsmgr)
        {
            Init();
            flowId = Xmlhelper.GetNodeText(nodeArtefact, string.Format("./structure:{0}", tagFlowid), nsmgr);
        }
        #endregion
    }


    public class DataFlowrefList : List<DataFlowRef>, IDatatableExchange
    {
        #region Table representation

        public static DataTable CreateTable()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn("Ref", typeof(bool)));
            dataTable.Columns.Add(new DataColumn("ID", typeof(string)));
            dataTable.Columns.Add(new DataColumn("AgencyID", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Version", typeof(string)));
            dataTable.Columns.Add(new DataColumn("URN", typeof(string)));

            return dataTable;
        }

        /// <summary>Presents flow as datatable</summary>
        /// <returns>a datatable representation</returns>
        public DataTable AsDataTable()
        {
            DataTable dataTable = CreateTable();

            foreach (DataFlowRef fr in this)
                dataTable.Rows.Add(new object[] { false, fr.FlowId, fr.AgencyId, fr.Version, fr.URI });

            return dataTable;
        }

        public void FromDataTable(DataTable tb)
        {
            this.Clear();
            foreach (DataRow row in tb.Rows)
            {
                DataFlowRef fr = new DataFlowRef();
                fr.FlowId = row[1].ToString();
                fr.AgencyId = row[2].ToString();
                fr.Version = row[3].ToString();
                fr.URI = row[4].ToString();
                this.Add(fr);
            }
        }
        #endregion
    }

    public class MetaDataFlowrefList : List<MetaDataFlowRef>, IDatatableExchange
    {
        #region Table representation

        /// <summary>Presents flow as datatable</summary>
        /// <returns>a datatable representation</returns>
        public DataTable AsDataTable()
        {
            DataTable dataTable = DataFlowrefList.CreateTable();

            foreach (MetaDataFlowRef fr in this)
                dataTable.Rows.Add(new object[] { false, fr.FlowId, fr.AgencyId, fr.Version, fr.URI });

            return dataTable;
        }

        public void FromDataTable(DataTable tb)
        {
            this.Clear();
            foreach (DataRow row in tb.Rows)
            {
                MetaDataFlowRef fr = new MetaDataFlowRef();
                fr.FlowId = row[1].ToString();
                fr.AgencyId = row[2].ToString();
                fr.Version = row[3].ToString();
                fr.URI = row[4].ToString();
                this.Add(fr);
            }
        }
        #endregion

    }
}
